package main

import (
	"bufio"
	"fmt"
	"os/exec"
	"sync"
)

// 示例1: 简单命令执行
func simpleCommand() {
	fmt.Println("\n=== 示例1: 简单命令执行 ===")

	// Linux 命令：输出信息并 ping 本地主机
	cmd := exec.Command("bash", "-c", "echo '这是一个简单命令' && ping -c 2 127.0.0.1")
	output, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Printf("命令执行错误: %v\n", err)
		return
	}
	fmt.Printf("命令输出:\n%s\n", string(output))
}

// 示例2: 实时输出处理
func realTimeOutput() {
	fmt.Println("\n=== 示例2: 实时输出处理 ===")

	// Linux 命令：分阶段输出，中间有延迟
	cmd := exec.Command("bash", "-c", "echo '第一行' && sleep 1 && echo '第二行' && sleep 1 && echo '第三行'")

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Printf("创建输出管道错误: %v\n", err)
		return
	}

	if err := cmd.Start(); err != nil {
		fmt.Printf("启动命令错误: %v\n", err)
		return
	}

	// 实时读取输出
	scanner := bufio.NewScanner(stdout)
	go func() {
		for scanner.Scan() {
			fmt.Printf("实时输出: %s\n", scanner.Text())
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("读取输出错误: %v\n", err)
		}
	}()

	if err := cmd.Wait(); err != nil {
		fmt.Printf("命令执行错误: %v\n", err)
	}
}

// 示例3: 同时处理标准输出和标准错误
func handleStdoutAndStderr() {
	fmt.Println("\n=== 示例3: 处理标准输出和标准错误 ===")

	// Linux 命令：输出正常信息并尝试列出不存在的目录
	cmd := exec.Command("bash", "-c", "echo '正常输出' && ls /不存在的目录")

	// 获取标准输出和标准错误管道
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Printf("创建标准输出管道错误: %v\n", err)
		return
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Printf("创建标准错误管道错误: %v\n", err)
		return
	}

	// 启动命令
	if err := cmd.Start(); err != nil {
		fmt.Printf("启动命令错误: %v\n", err)
		return
	}

	// 使用 WaitGroup 等待两个 goroutine 完成
	var wg sync.WaitGroup
	wg.Add(2)

	// 并行读取标准输出
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stdout)
		lineCount := 0
		for scanner.Scan() {
			lineCount++
			line := scanner.Text()
			fmt.Printf("STDOUT[%d]: %s\n", lineCount, line)
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("读取标准输出错误: %v\n", err)
		}
		fmt.Println("标准输出读取完成")
	}()

	// 并行读取标准错误
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stderr)
		lineCount := 0
		for scanner.Scan() {
			lineCount++
			line := scanner.Text()
			fmt.Printf("STDERR[%d]: %s\n", lineCount, line)
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("读取标准错误错误: %v\n", err)
		}
		fmt.Println("标准错误读取完成")
	}()

	// 等待读取完成
	wg.Wait()

	// 等待命令完成
	if err := cmd.Wait(); err != nil {
		fmt.Printf("命令退出错误: %v\n", err)
	} else {
		fmt.Println("命令执行完成")
	}
}

// 示例4: 带错误处理的改进版本
func improvedStdoutStderr() {
	fmt.Println("\n=== 示例4: 改进版输出错误处理 ===")

	// Linux 命令：混合正常输出和错误输出
	cmd := exec.Command("bash", "-c", "echo '正常输出开始' && ls /不存在的目录 && echo '正常输出结束'")

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Printf("创建标准输出管道错误: %v\n", err)
		return
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Printf("创建标准错误管道错误: %v\n", err)
		return
	}

	if err := cmd.Start(); err != nil {
		fmt.Printf("启动命令错误: %v\n", err)
		return
	}

	var wg sync.WaitGroup
	wg.Add(2)

	// 创建通道用于 goroutine 间通信
	stdoutLines := make(chan string, 10)
	stderrLines := make(chan string, 10)
	done := make(chan bool, 2)

	// 读取标准输出
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			stdoutLines <- scanner.Text()
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("标准输出读取错误: %v\n", err)
		}
		close(stdoutLines)
	}()

	// 读取标准错误
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stderr)
		for scanner.Scan() {
			stderrLines <- scanner.Text()
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("标准错误读取错误: %v\n", err)
		}
		close(stderrLines)
	}()

	// 处理输出的 goroutine
	go func() {
		stdoutClosed := false
		stderrClosed := false

		for {
			select {
			case line, ok := <-stdoutLines:
				if !ok {
					stdoutClosed = true
					stdoutLines = nil
				} else {
					fmt.Printf("🔵 STDOUT: %s\n", line)
				}
			case line, ok := <-stderrLines:
				if !ok {
					stderrClosed = true
					stderrLines = nil
				} else {
					fmt.Printf("🔴 STDERR: %s\n", line)
				}
			}

			if stdoutClosed && stderrClosed {
				done <- true
				return
			}
		}
	}()

	// 等待读取完成
	wg.Wait()

	// 等待处理完成
	<-done

	// 等待命令完成
	if err := cmd.Wait(); err != nil {
		fmt.Printf("命令退出状态: %v\n", err)
	} else {
		fmt.Println("✅ 命令执行成功")
	}
}

// 示例5: 系统信息收集
func systemInfoCollection() {
	fmt.Println("\n=== 示例5: 系统信息收集 ===")

	// 收集系统信息的命令
	cmd := exec.Command("bash", "-c", `
		echo "=== 系统信息 ==="
		uname -a
		echo "=== 内存使用 ==="
		free -h
		echo "=== 磁盘空间 ==="
		df -h / | tail -1
		echo "=== 当前用户 ==="
		whoami
	`)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Printf("创建标准输出管道错误: %v\n", err)
		return
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Printf("创建标准错误管道错误: %v\n", err)
		return
	}

	if err := cmd.Start(); err != nil {
		fmt.Printf("启动命令错误: %v\n", err)
		return
	}

	var wg sync.WaitGroup
	wg.Add(2)

	// 读取标准输出
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			line := scanner.Text()
			fmt.Printf("📊 %s\n", line)
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("读取标准输出错误: %v\n", err)
		}
	}()

	// 读取标准错误
	go func() {
		defer wg.Done()
		scanner := bufio.NewScanner(stderr)
		for scanner.Scan() {
			line := scanner.Text()
			fmt.Printf("⚠️  STDERR: %s\n", line)
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("读取标准错误错误: %v\n", err)
		}
	}()

	// 等待读取完成
	wg.Wait()

	// 等待命令完成
	if err := cmd.Wait(); err != nil {
		fmt.Printf("命令退出错误: %v\n", err)
	} else {
		fmt.Println("系统信息收集完成")
	}
}

// 示例6: 进程监控示例
func processMonitoring() {
	fmt.Println("\n=== 示例6: 进程监控示例 ===")

	// 监控系统进程（运行5秒）
	cmd := exec.Command("bash", "-c", `
		echo "开始监控进程（5秒）..."
		for i in $(seq 1 5); do
			echo "=== 第 $i 次采样 ==="
			ps aux --sort=-%cpu | head -5
			sleep 1
		done
		echo "监控结束"
	`)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Printf("创建输出管道错误: %v\n", err)
		return
	}

	if err := cmd.Start(); err != nil {
		fmt.Printf("启动命令错误: %v\n", err)
		return
	}

	// 实时读取监控输出
	scanner := bufio.NewScanner(stdout)
	go func() {
		for scanner.Scan() {
			line := scanner.Text()
			fmt.Printf("📈 %s\n", line)
		}
		if err := scanner.Err(); err != nil {
			fmt.Printf("读取监控输出错误: %v\n", err)
		}
	}()

	if err := cmd.Wait(); err != nil {
		fmt.Printf("监控命令执行错误: %v\n", err)
	} else {
		fmt.Println("进程监控完成")
	}
}

// 示例7: 文件操作示例
func fileOperations() {
	fmt.Println("\n=== 示例7: 文件操作示例 ===")

	// 创建测试文件并操作
	cmd := exec.Command("bash", "-c", `
		# 创建测试目录和文件
		mkdir -p /tmp/go_test
		cd /tmp/go_test
		echo "文件1内容" > file1.txt
		echo "文件2内容" > file2.txt
		echo "=== 目录内容 ==="
		ls -la
		echo "=== 文件内容 ==="
		cat *.txt
		echo "=== 清理 ==="
		cd /tmp
		rm -rf go_test
		echo "文件操作完成"
	`)

	output, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Printf("文件操作错误: %v\n", err)
		return
	}
	fmt.Printf("文件操作输出:\n%s\n", string(output))
}

func main() {
	fmt.Println("=== Go Linux 命令执行示例程序 ===")
	fmt.Println("演示如何在 Linux 中执行外部命令并处理输出")

	// 执行示例1 - 简单命令
	simpleCommand()

	// 执行示例2 - 实时输出
	realTimeOutput()

	// 执行示例3 - 主要的并发处理示例
	handleStdoutAndStderr()

	// 执行示例4 - 改进版本
	improvedStdoutStderr()

	// 执行示例5 - 系统信息收集
	systemInfoCollection()

	// 执行示例6 - 进程监控
	processMonitoring()

	// 执行示例7 - 文件操作
	fileOperations()

	fmt.Println("\n=== 所有示例执行完成 ===")
	fmt.Println("总结:")
	fmt.Println("1. simpleCommand: 使用 CombinedOutput 简单执行")
	fmt.Println("2. realTimeOutput: 实时输出处理")
	fmt.Println("3. handleStdoutStderr: 主要示例 - 并发处理 stdout/stderr")
	fmt.Println("4. improvedStdoutStderr: 改进版使用通道")
	fmt.Println("5. systemInfoCollection: 系统信息收集")
	fmt.Println("6. processMonitoring: 进程监控")
	fmt.Println("7. fileOperations: 文件操作示例")
}
